package org.acghub.mtdb.core.log.impl;

import org.acghub.mtdb.core.LogKey;
import org.acghub.mtdb.core.log.LogAbstractCollection;

import java.util.Deque;
import java.util.Iterator;

public final class LogDeque<E> extends LogAbstractCollection<E> implements Deque<E> {
    public LogDeque(LogKey logkey, Deque<E> wrapped) {
        super(logkey, wrapped);
    }

    private LogDeque(LogAbstractCollection<E> root, Deque<E> wrapped) {
        super(root, wrapped);
    }

    @Override
    public void addFirst(E e) {
        onChange();
        wrapped().addFirst(e);
        onAdd(e);
    }

    @Override
    public void addLast(E e) {
        onChange();
        wrapped().addLast(e);
        onAdd(e);
    }

    @Override
    public boolean offerFirst(E e) {
        onChange();
        if (wrapped().offerFirst(e)) {
            onAdd(e);
            return true;
        }
        return false;
    }

    @Override
    public boolean offerLast(E e) {
        onChange();
        if (wrapped().offerLast(e)) {
            onAdd(e);
            return true;
        }
        return false;
    }

    @Override
    public E removeFirst() {
        onChange();
        E e = wrapped().removeFirst();
        onRemove(e);
        return e;
    }

    @Override
    public E removeLast() {
        onChange();
        E e = wrapped().removeLast();
        onRemove(e);
        return e;
    }

    @Override
    public E pollFirst() {
        onChange();
        E e = wrapped().pollFirst();
        onRemove(e);
        return e;
    }

    @Override
    public E pollLast() {
        onChange();
        E e = wrapped().pollLast();
        onRemove(e);
        return e;
    }

    @Override
    public E getFirst() {
        return wrapped().getFirst();
    }

    @Override
    public E getLast() {
        return wrapped().pollLast();
    }

    @Override
    public E peekFirst() {
        return wrapped().peekFirst();
    }

    @Override
    public E peekLast() {
        return wrapped().peekLast();
    }

    @Override
    public boolean removeFirstOccurrence(Object o) {
        onChange();
        if (wrapped().removeFirstOccurrence(o)) {
            onRemove((E) o);
            return true;
        }
        return false;
    }

    @Override
    public boolean removeLastOccurrence(Object o) {
        onChange();
        if (wrapped().removeLastOccurrence(o)) {
            onRemove((E) o);
            return true;
        }
        return false;
    }

    @Override
    public boolean offer(E e) {
        onChange();
        if (wrapped().offer(e)) {
            onAdd(e);
            return true;
        }
        return false;
    }

    @Override
    public E remove() {
        onChange();
        E e = wrapped().remove();
        onRemove(e);
        return e;
    }

    @Override
    public E poll() {
        onChange();
        E e = wrapped().poll();
        onRemove(e);
        return e;
    }

    @Override
    public E element() {
        return wrapped().element();
    }

    @Override
    public E peek() {
        return wrapped().peek();
    }

    @Override
    public void push(E e) {
        onChange();
        wrapped().push(e);
        onAdd(e);
    }

    @Override
    public E pop() {
        onChange();
        E e = wrapped().pop();
        onRemove(e);
        return e;
    }

    @Override
    public Iterator<E> descendingIterator() {
        return new LogIte(wrapped().descendingIterator());
    }


    @Override
    protected Deque<E> wrapped() {
        return (Deque<E>) wrapped;
    }
}
